// ============================================================================
//
// Copyright (C) 2006-2007 Dengues
//
// Google Group: http://groups.google.com/group/dengues
// QQ Group: 24885404
//
// This library is free software; you can redistribute it and/or
// modify it under the terms of the GNU Lesser General Public
// License as published by the Free Software Foundation; either
// version 2.1 of the License.
//
// This library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
// Lesser General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
//
// ============================================================================
package org.dengues.designer.ui.actions;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.SocketException;

import org.dengues.commons.IDenguesSharedImage;
import org.dengues.commons.utils.ImageUtil;
import org.dengues.core.CorePlugin;
import org.dengues.core.ExceptionOperation;
import org.dengues.core.IDesignerUIService;
import org.dengues.core.prefs.IDenguesPrefsConstant;
import org.dengues.core.process.ICompProcess;
import org.dengues.core.runprocess.IJavaETLProcessor;
import org.dengues.designer.ui.database.editors.DBFileEditorInput;
import org.dengues.designer.ui.database.editors.GEFDatabaseEditor;
import org.dengues.designer.ui.editors.DatabaseMultiEditor;
import org.dengues.designer.ui.editors.ProcessMultiEditor;
import org.dengues.designer.ui.i18n.Messages;
import org.dengues.designer.ui.process.editors.GEFComponentsEditor;
import org.dengues.designer.ui.process.editors.ProcessEditorInput;
import org.dengues.designer.ui.process.models.CompConnection;
import org.dengues.designer.ui.process.models.CompProcess;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.jface.action.Action;
import org.eclipse.swt.widgets.Display;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.PlatformUI;

/**
 * Qiang.Zhang.Adolf@gmail.com class global comment. Detailled comment <br/>
 * 
 * @since 2007-10-26 下午11:46:58
 */
public class LaunchEditorAction extends Action {

    private int status = IDesignerUIService.STATUS_STOP;

    private ICompProcess process;

    private ServerSocket serverSock = null;

    public LaunchEditorAction() {

        super(Messages.getString("RunDataBaseAction.Text")); //$NON-NLS-1$
        setEnabled(false);
        setImageDescriptor(ImageUtil.getDescriptor(IDenguesSharedImage.TOOLBAR_RUN));
        setDisabledImageDescriptor(ImageUtil.getDescriptor(IDenguesSharedImage.TOOLBAR_DISABLERUN));
        final int acceptTimeout = 30000;
        try {
            serverSock = new ServerSocket(CorePlugin.getDefault().getPreferenceStore().getInt(IDenguesPrefsConstant.SOCKET_PORT));
            serverSock.setSoTimeout(acceptTimeout);
        } catch (SocketException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /*
     * (non-Javadoc)
     * 
     * @see org.eclipse.jface.action.Action#run()
     */
    @Override
    public void run() {
        IWorkbenchPart activePart = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActiveEditor();
        if (activePart instanceof ProcessMultiEditor) {
            if (status == IDesignerUIService.STATUS_STOP) {
                setStatus(IDesignerUIService.STATUS_RUN);
                setImageDescriptor(ImageUtil.getDescriptor(IDenguesSharedImage.TOOLBAR_PAUSE));
                runProcess(activePart);
            } else if (status == IDesignerUIService.STATUS_RUN) {
                setStatus(IDesignerUIService.STATUS_PAUSE);
                setImageDescriptor(ImageUtil.getDescriptor(IDenguesSharedImage.TOOLBAR_RUN));
            } else if (status == IDesignerUIService.STATUS_PAUSE) {
                setStatus(IDesignerUIService.STATUS_RUN);
                setImageDescriptor(ImageUtil.getDescriptor(IDenguesSharedImage.TOOLBAR_PAUSE));
            }
        } else if (activePart instanceof DatabaseMultiEditor) {
            DatabaseMultiEditor part = (DatabaseMultiEditor) activePart;
            GEFDatabaseEditor gefDBEditor = part.getGefDBEditor();
            DBFileEditorInput fileEditorInput = (DBFileEditorInput) gefDBEditor.getEditorInput();
            String sqlStatement = fileEditorInput.getSqlStatement();
            try {
                // ConnectivityManager.getConnection(fileEditorInput.getDbDiagram().getProperties());
                // Statement createStatement = ConnectivityManager.getConnection().createStatement();
                // createStatement.execute(sqlStatement);
                CorePlugin.getDefault().getDesignerCoreService().runSqlScript(fileEditorInput.getSqlScriptFile(),
                        fileEditorInput.getDbDiagram().getProperties());
            } catch (Exception ex) {
                ExceptionOperation.operate(ex);
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "runProcess".
     * 
     * @param activePart
     */
    private void runProcess(IWorkbenchPart activePart) {
        ProcessMultiEditor part = (ProcessMultiEditor) activePart;
        GEFComponentsEditor gefCompEditor = part.getGefCompEditor();
        process = gefCompEditor.getProcess();
        IJavaETLProcessor javaProcessor = CorePlugin.getDefault().getDesignerCoreService().getJavaProcessor(process,
                ((ProcessEditorInput) gefCompEditor.getEditorInput()).getPath());
        try {
            new Thread(new Runnable() {

                /*
                 * (non-Javadoc)
                 * 
                 * @see java.lang.Runnable#run()
                 */
                public void run() {
                    stopThread = false;
                    runProcess();
                }
            }).start();
            ILaunch launch = javaProcessor.launch();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public int getStatus() {
        return this.status;
    }

    public void setStatus(int status) {
        this.status = status;
    }

    private boolean stopThread;

    public void runProcess() {
        Socket processSocket = null;
        do {
            try {
                processSocket = serverSock.accept();
            } catch (IOException e) {
                e.printStackTrace();
                try {
                    if (serverSock != null) {
                        serverSock.close();
                    }
                } catch (IOException e1) {
                    e1.printStackTrace();
                } finally {
                    try {
                        if (serverSock != null) {
                            serverSock.close();
                        }
                    } catch (IOException e1) {
                        e1.printStackTrace();
                    }
                }
            } catch (Exception ex) {
                ex.printStackTrace();
            }
        } while (processSocket == null && !stopThread);
        if (processSocket != null && !stopThread) {
            try {
                InputStream in = processSocket.getInputStream();
                LineNumberReader reader = new LineNumberReader(new InputStreamReader(in));
                while (!stopThread) {
                    final String data = reader.readLine();
                    PrintWriter pred = new java.io.PrintWriter(new java.io.BufferedWriter(new java.io.OutputStreamWriter(
                            processSocket.getOutputStream())), true);
                    if (isProcessPause()) {
                        pred.println("PAUSE"); //$NON-NLS-1$
                    } else {
                        pred.println("RUN"); //$NON-NLS-1$
                    }
                    if (data == null) {
                        stopThread = true;
                        setStatus(IDesignerUIService.STATUS_STOP);
                        setImageDescriptor(ImageUtil.getDescriptor(IDenguesSharedImage.TOOLBAR_RUN));
                    } else if ("STATUS".equals(data)) { //$NON-NLS-1$
                        continue;
                    } else {
                        Display.getDefault().asyncExec(new Runnable() {

                            /*
                             * (non-Javadoc)
                             * 
                             * @see java.lang.Runnable#run()
                             */
                            public void run() {
                                if (data != null) {
                                    CompProcess compProcess = (CompProcess) process;
                                    int indexOf = data.indexOf("->"); //$NON-NLS-1$
                                    int seqIndex = data.indexOf(" "); //$NON-NLS-1$
                                    if (seqIndex > 0 && indexOf > seqIndex) {
                                        String name = data.substring(0, seqIndex).trim();
                                        CompConnection connection = (CompConnection) compProcess.findConnection(name);
                                        if (connection != null) {
                                            connection.getConnectionTrac().setConnectionTrac(data);
                                        }
                                    }
                                }
                            }

                        });
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    processSocket.close();
                } catch (IOException ioe) {
                    ioe.printStackTrace();
                }
            }
        }
    }

    /**
     * Qiang.Zhang.Adolf@gmail.com Comment method "isTracPause".
     * 
     * @return
     */
    private boolean isProcessPause() {
        return status == IDesignerUIService.STATUS_PAUSE;
    }

    /**
     * Sets the stopThread.
     * 
     * @param stopThread the stopThread to set
     */
    public void setStopThread(boolean stopThread) {
        this.stopThread = stopThread;
    }

}
